package nginx

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/acepanel/panel/pkg/webserver/types"
)

// proxyFilePattern 匹配代理配置文件名 (200-299)
var proxyFilePattern = regexp.MustCompile(`^(\d{3})-proxy\.conf$`)

// parseProxyFiles 从 site 目录解析所有代理配置
func parseProxyFiles(siteDir string) ([]types.Proxy, error) {
	entries, err := os.ReadDir(siteDir)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	var proxies []types.Proxy
	for _, entry := range entries {
		if entry.IsDir() {
			continue
		}

		matches := proxyFilePattern.FindStringSubmatch(entry.Name())
		if matches == nil {
			continue
		}

		num, _ := strconv.Atoi(matches[1])
		if num < ProxyStartNum || num > ProxyEndNum {
			continue
		}

		filePath := filepath.Join(siteDir, entry.Name())
		proxy, err := parseProxyFile(filePath)
		if err != nil {
			continue // 跳过解析失败的文件
		}
		if proxy != nil {
			proxies = append(proxies, *proxy)
		}
	}

	return proxies, nil
}

// parseProxyFile 解析单个代理配置文件
func parseProxyFile(filePath string) (*types.Proxy, error) {
	content, err := os.ReadFile(filePath)
	if err != nil {
		return nil, err
	}

	contentStr := string(content)

	// 解析 location 块
	// location / {
	//     proxy_pass http://backend;
	//     ...
	// }
	locationPattern := regexp.MustCompile(`location\s+([^{]+)\{([^}]+(?:\{[^}]*}[^}]*)*)}`)
	matches := locationPattern.FindStringSubmatch(contentStr)
	if matches == nil {
		return nil, nil
	}

	proxy := &types.Proxy{
		Location: strings.TrimSpace(matches[1]),
		Replaces: make(map[string]string),
	}

	blockContent := matches[2]

	// 解析 proxy_pass
	passPattern := regexp.MustCompile(`proxy_pass\s+([^;]+);`)
	if pm := passPattern.FindStringSubmatch(blockContent); pm != nil {
		proxy.Pass = strings.TrimSpace(pm[1])
	}

	// 解析 proxy_set_header Host
	hostPattern := regexp.MustCompile(`proxy_set_header\s+Host\s+([^;]+);`)
	if hm := hostPattern.FindStringSubmatch(blockContent); hm != nil {
		host := strings.TrimSpace(hm[1])
		// 移除引号
		host = strings.Trim(host, `"'`)
		if host != "$host" && host != "$http_host" {
			proxy.Host = host
		}
	}

	// 解析 proxy_ssl_name (SNI)
	sniPattern := regexp.MustCompile(`proxy_ssl_name\s+([^;]+);`)
	if sm := sniPattern.FindStringSubmatch(blockContent); sm != nil {
		proxy.SNI = strings.TrimSpace(sm[1])
	}

	// 解析 proxy_buffering
	bufferingPattern := regexp.MustCompile(`proxy_buffering\s+(on|off);`)
	if bm := bufferingPattern.FindStringSubmatch(blockContent); bm != nil {
		proxy.Buffering = bm[1] == "on"
	}

	// 解析 proxy_cache
	cachePattern := regexp.MustCompile(`proxy_cache\s+(\S+);`)
	if cm := cachePattern.FindStringSubmatch(blockContent); cm != nil && cm[1] != "off" {
		proxy.Cache = true
	}

	// 解析 resolver
	resolverPattern := regexp.MustCompile(`resolver\s+([^;]+);`)
	if rm := resolverPattern.FindStringSubmatch(blockContent); rm != nil {
		parts := strings.Fields(rm[1])
		proxy.Resolver = parts
		proxy.AutoRefresh = true // 有 resolver 通常意味着需要自动刷新
	}

	// 解析 resolver_timeout
	resolverTimeoutPattern := regexp.MustCompile(`resolver_timeout\s+(\d+)([smh]?);`)
	if rtm := resolverTimeoutPattern.FindStringSubmatch(blockContent); rtm != nil {
		value, _ := strconv.Atoi(rtm[1])
		unit := rtm[2]
		switch unit {
		case "m":
			proxy.ResolverTimeout = time.Duration(value) * time.Minute
		case "h":
			proxy.ResolverTimeout = time.Duration(value) * time.Hour
		default:
			proxy.ResolverTimeout = time.Duration(value) * time.Second
		}
	}

	// 解析 sub_filter (响应内容替换)
	subFilterPattern := regexp.MustCompile(`sub_filter\s+"([^"]+)"\s+"([^"]*)";`)
	subFilterMatches := subFilterPattern.FindAllStringSubmatch(blockContent, -1)
	for _, sfm := range subFilterMatches {
		proxy.Replaces[sfm[1]] = sfm[2]
	}

	return proxy, nil
}

// writeProxyFiles 将代理配置写入文件
func writeProxyFiles(siteDir string, proxies []types.Proxy) error {
	// 删除现有的代理配置文件 (200-299)
	if err := clearProxyFiles(siteDir); err != nil {
		return err
	}

	// 写入新的配置文件
	for i, proxy := range proxies {
		num := ProxyStartNum + i
		if num > ProxyEndNum {
			return fmt.Errorf("proxy rules exceed limit (%d)", ProxyEndNum-ProxyStartNum+1)
		}

		fileName := fmt.Sprintf("%03d-proxy.conf", num)
		filePath := filepath.Join(siteDir, fileName)

		content := generateProxyConfig(proxy)
		if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
			return fmt.Errorf("failed to write proxy config: %w", err)
		}
	}

	return nil
}

// clearProxyFiles 清除所有代理配置文件
func clearProxyFiles(siteDir string) error {
	entries, err := os.ReadDir(siteDir)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return err
	}

	for _, entry := range entries {
		if entry.IsDir() {
			continue
		}

		matches := proxyFilePattern.FindStringSubmatch(entry.Name())
		if matches == nil {
			continue
		}

		num, _ := strconv.Atoi(matches[1])
		if num >= ProxyStartNum && num <= ProxyEndNum {
			filePath := filepath.Join(siteDir, entry.Name())
			if err := os.Remove(filePath); err != nil && !os.IsNotExist(err) {
				return fmt.Errorf("failed to delete proxy config: %w", err)
			}
		}
	}

	return nil
}

// generateProxyConfig 生成代理配置内容
func generateProxyConfig(proxy types.Proxy) string {
	var sb strings.Builder

	location := proxy.Location
	if location == "" {
		location = "/"
	}

	sb.WriteString(fmt.Sprintf("location %s {\n", location))

	// resolver 配置（如果启用自动刷新）
	if proxy.AutoRefresh && len(proxy.Resolver) > 0 {
		sb.WriteString(fmt.Sprintf("    resolver %s;\n", strings.Join(proxy.Resolver, " ")))
		if proxy.ResolverTimeout > 0 {
			sb.WriteString(fmt.Sprintf("    resolver_timeout %ds;\n", int(proxy.ResolverTimeout.Seconds())))
		}
		// 使用变量实现动态解析
		sb.WriteString(fmt.Sprintf("    set $backend \"%s\";\n", proxy.Pass))
		sb.WriteString("    proxy_pass $backend;\n")
	} else {
		sb.WriteString(fmt.Sprintf("    proxy_pass %s;\n", proxy.Pass))
	}

	// Host 头
	if proxy.Host != "" {
		sb.WriteString(fmt.Sprintf("    proxy_set_header Host \"%s\";\n", proxy.Host))
	} else {
		sb.WriteString("    proxy_set_header Host $host;\n")
	}

	// 标准代理头
	sb.WriteString("    proxy_set_header X-Real-IP $remote_addr;\n")
	sb.WriteString("    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
	sb.WriteString("    proxy_set_header X-Forwarded-Proto $scheme;\n")

	// SNI 配置
	if proxy.SNI != "" {
		sb.WriteString("    proxy_ssl_server_name on;\n")
		sb.WriteString(fmt.Sprintf("    proxy_ssl_name %s;\n", proxy.SNI))
	}

	// Buffering 配置
	if proxy.Buffering {
		sb.WriteString("    proxy_buffering on;\n")
	} else {
		sb.WriteString("    proxy_buffering off;\n")
	}

	// Cache 配置
	if proxy.Cache {
		sb.WriteString("    proxy_cache proxy_cache;\n")
		sb.WriteString("    proxy_cache_valid 200 302 10m;\n")
		sb.WriteString("    proxy_cache_valid 404 1m;\n")
	}

	// 响应内容替换
	if len(proxy.Replaces) > 0 {
		sb.WriteString("    proxy_set_header Accept-Encoding \"\";\n")
		sb.WriteString("    sub_filter_once off;\n")
		for from, to := range proxy.Replaces {
			sb.WriteString(fmt.Sprintf("    sub_filter \"%s\" \"%s\";\n", from, to))
		}
	}

	sb.WriteString("}\n")

	return sb.String()
}
